package rsj.proxy.strategy;

import rsj.context.ApplicationContextUtil;
import rsj.proxy.ExecuteStatementProcessorFactory;
import rsj.proxy.PreExecuteStatementProcessor;
import rsj.proxy.bind.AbstractParamResolveFactory;
import rsj.proxy.parse.SqlSource;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.Objects;

/**
 * 按sql注解不同类型执行不同逻辑、
 *
 * @author yuanqinglong
 * @since 2021/5/8 10:03
 */
public interface IExecuteStrategy {


    /**
     * 得到支持注释类型
     *
     * @return boolean
     */
    Class<?> getSupportAnnotationType();


    /**
     * 执行查询逻辑
     *
     * @param connection 数据库连接
     * @param method     声明sql的方法
     * @param args       参数
     * @return 结果
     * @throws Exception 异常
     */
    Object executeStrategy(Connection connection, Method method, Object[] args) throws Exception;

    /**
     * 根据sql声明方法返回类型找到对应执行方法
     *
     * @param method sql声明方法
     * @return PreExecuteStatementProcessor
     * @throws Exception 异常
     */
    default PreExecuteStatementProcessor getExecuteProcessor(Method method) throws Exception {
        // 根据声sql方法的返回类型 回去对应的执行器
        PreExecuteStatementProcessor statementProcessor = ExecuteStatementProcessorFactory.getPreExecuteStatementProcessor(method.getReturnType());
        if (Objects.isNull(statementProcessor)) {
            throw new RuntimeException("不支持" + method.getReturnType().getSimpleName() + "返回类型");
        }
        return statementProcessor;
    }


    /**
     * 参数解析
     *
     * @param sqlSource sql源
     * @param method    方法
     * @param args      arg
     *
     * @return {@link Object[]}
     * @throws Exception 异常
     */
    default Object[] paramResolve(SqlSource sqlSource, Method method, Object[] args) throws Exception {
        AbstractParamResolveFactory paramResolveFactory = ApplicationContextUtil.getBean(AbstractParamResolveFactory.class);
        return paramResolveFactory.doParameterAnalysis(sqlSource, method, args);
    }


    /**
     * 打印sql
     *
     * @param sqlSource sql源
     * @param args      arg游戏
     * @return {@link String}
     */
    default String printSql(SqlSource sqlSource, Object[] args) {
        String finalSql = sqlSource.getFinalSql();
//        List<ParameterMapping> parameterMappings = sqlSource.getParameterMappings();
//        int count = 0;
//        if (!parameterMappings.isEmpty() && args.length > 0) {
//            for (int i = 0; i < finalSql.length(); i++) {
//                if (finalSql.charAt(i) == '?') {
//                    Object param = args[count];
//                    if (param instanceof String) {
//                        finalSql = finalSql.substring(0,i)+"'" + param + "'"+finalSql.substring(i+1);
////                        finalSql = finalSql.replaceFirst("\\?", "'" + param + "'");
//                    } else if (param.getClass() == LocalDate.class) {
//                        String stringDate = DateTimeFormatterUtil.localDateFormatterToStringDate((LocalDate) param);
////                        finalSql = finalSql.replaceFirst("\\?", "'" + stringDate + "'");
//                        finalSql = finalSql.substring(0,i)+"'" + stringDate + "'"+finalSql.substring(i+1);
//                    } else if (param.getClass() == LocalDateTime.class) {
//                        String stringDateTime = DateTimeFormatterUtil.dateTimeToString((LocalDateTime) param);
////                        finalSql = finalSql.replaceFirst("\\?", "'" + stringDateTime + "'");
//                        finalSql = finalSql.substring(0,i)+"'" + stringDateTime + "'"+finalSql.substring(i+1);
//                    } else {
////                        finalSql = finalSql.replaceFirst("\\?", param + "");
//                        finalSql = finalSql.substring(0,i)+param+finalSql.substring(i+1);
//                    }
//                    count++;
//                }
//            }
//        }
        return finalSql;
    }
}
